from tkx.counts import attrs as A
from tkx.utils import *
from typing import *

False_ = False
if False_:
    from tkx.__init__ import *
    from tkx.widget_parse import BuildingWidget

command_attribute = [A.command, A.postcommand, A.validatecommand, A.xscrollcommand, A.yscrollcommand]
place_func_attribute = [A.expand, A.padx, A.pady, A.ipadx, A.ipady, A.fill, A.side, A.anchor]

attribute_parsers: Dict[str, Callable[['BuildingWidget', str, 'TkxWindow'], NoReturn]] = {}


def attribute_parser(name: str):
    def w(func):
        attribute_parsers[name] = func
        return func

    return w


@attribute_parser(A.text)
def attribute_parser_text(bw: 'BuildingWidget', value: str, window: 'TkxWindow'):
    bw.widget['text'] = value.replace(r'\n', '\n')


@attribute_parser(A.width)
def attribute_parser_width(bw: 'BuildingWidget', value: str, window: 'TkxWindow'):
    if value == 'fill':
        if 'fill' in bw.place_args and bw.place_args['fill'] == 'y':
            bw.place_args['fill'] = 'both'
        else:
            bw.place_args['fill'] = 'x'
    else:
        bw.widget['width'] = value


@attribute_parser(A.height)
def attribute_parser_height(bw: 'BuildingWidget', value: str, window: 'TkxWindow'):
    if value == 'fill':
        if 'fill' in bw.place_args and bw.place_args['fill'] == 'x':
            bw.place_args['fill'] = 'both'
        else:
            bw.place_args['fill'] = 'y'
    else:
        bw.widget['height'] = value


@attribute_parser(A.name)
def attribute_parser_name(bw: 'BuildingWidget', value: str, window: 'TkxWindow'):
    if value in window.widgets:
        raise Exception(f"名称已经存在了：{value}")
    window.widgets[value] = bw.widget


@attribute_parser(A.pad)
def attribute_parser_pad(bw: 'BuildingWidget', value: str, window: 'TkxWindow'):
    xy = [i.strip() for i in value.split('x') if i.strip()]
    if len(xy) == 1:
        bw.place_args['padx'] = xy[0]
        bw.place_args['pady'] = xy[0]
    elif len(xy) == 2:
        bw.place_args['padx'] = xy[0]
        bw.place_args['pady'] = xy[1]
    else:
        raise Exception(f"{A.pad} 需要两个参数，这两个参数用 x 分开.")


@attribute_parser(A.ipad)
def attribute_parser_ipad(bw: 'BuildingWidget', value: str, window: 'TkxWindow'):
    xy = [i.strip() for i in value.split('x') if i.strip()]
    if len(xy) == 1:
        bw.place_args['ipadx'] = xy[0]
        bw.place_args['ipady'] = xy[0]
    elif len(xy) == 2:
        bw.place_args['ipadx'] = xy[0]
        bw.place_args['ipady'] = xy[1]
    else:
        raise Exception(f"{A.ipad} 需要两个参数，这两个参数用 x 分开.")


@attribute_parser(A.align)
def attribute_parser_align(bw: 'BuildingWidget', value: str, window: 'TkxWindow'):
    bw.children_place_args['anchor'] = value


@attribute_parser(A.child_side)
def attribute_parser_child_side(bw: 'BuildingWidget', value: str, window: 'TkxWindow'):
    bw.children_place_args['side'] = value


@attribute_parser(A.textvariable)
@attribute_parser(A.textvar)
def attribute_parser_textvar(bw: 'BuildingWidget', value: str, window: 'TkxWindow'):
    bw.widget['textvariable'] = parse_var(window, value)


@attribute_parser(A.variable)
@attribute_parser(A.valuevar)
def attribute_parser_valuevar(bw: 'BuildingWidget', value: str, window: 'TkxWindow'):
    bw.widget['variable'] = parse_var(window, value)


@attribute_parser(A.on_place)
def attribute_parser_on_place(bw: 'BuildingWidget', value: str, window: 'TkxWindow'):
    bw.on_place = get_command(window, value)


@attribute_parser(A.data)
def attribute_parser_data(bw: 'BuildingWidget', value: str, window: 'TkxWindow'):
    bw.data = value


@attribute_parser(A.bind)
def attribute_parser_bind(bw: 'BuildingWidget', value: str, window: 'TkxWindow'):
    i = value.find(':')
    event = value[:i].strip()
    command = value[i + 1:].strip()
    bw.widget.bind(f'<{event}>', get_command(window, command))


def parse_widget_attribute(bw: 'BuildingWidget', attributes: Dict[str, str], window: 'TkxWindow'):
    """ 解析一个组件上的属性。
    """
    for att_name, value in attributes.items():
        if att_name in place_func_attribute:
            bw.place_args[att_name] = value
            continue
        if att_name in command_attribute:
            bw.widget[att_name] = get_command(window, attributes[att_name])
            continue
        if att_name in attribute_parsers:
            attribute_parsers[att_name](bw, value, window)
            continue
        bw.widget[att_name] = value
